home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dc1 / asmflt.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  18KB  |  917 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  ASMFLT.C
  9.  */
  10.  
  11. #include "defs.h"
  12. #include "asm.h"
  13. #undef abs
  14. #define abs   dummy    /*  bug in libraries/mathffp.h      */
  15. #ifdef AMIGA
  16. #include <exec/types.h>
  17. #include <exec/libraries.h>
  18. #include <clib/exec_protos.h>
  19. #endif
  20.  
  21. #ifdef NOTDEF
  22. #include <proto/mathffp.h>
  23. #include <proto/mathieeesingbas.h>
  24. #include <proto/mathieeedoubbas.h>
  25. #include <proto/mathieeedoubtrans.h>
  26. #endif
  27.  
  28. #include "ieee.h"
  29.  
  30. extern __stkargs long afp(char *);
  31.  
  32. typedef struct Library Library;
  33.  
  34. /*
  35.  *  warning, lib not automatically openned for lc_ version.  Thus, no
  36.  *  floating pt may be used in the compiler.  Also, we do not want the
  37.  *  compiler constant fp stuff to depend on the amiga libraries.
  38.  */
  39.  
  40. char MathMode = 'a';
  41.  
  42. static char TmpBuf[256];
  43.  
  44. Prototype void asm_fpadd(Exp *, Type *, Stor *, Stor *, Stor *);
  45. Prototype void asm_fpsub(Exp *, Type *, Stor *, Stor *, Stor *);
  46. Prototype void asm_fpmul(Exp *, Type *, Stor *, Stor *, Stor *);
  47. Prototype void asm_fpdiv(Exp *, Type *, Stor *, Stor *, Stor *);
  48. Prototype void asm_fpneg(Exp *, Type *, Stor *, Stor *);
  49. Prototype void asm_fpcmp(Exp *, Stor *, Stor *, short *);
  50. Prototype void asm_fptest(Exp *, Stor *);
  51. Prototype void asm_fptoint(Exp *, Stor *, Stor *);
  52. Prototype void asm_inttofp(Exp *, Stor *, Stor *);
  53. Prototype void asm_fptofp(Exp *, Stor *, Stor *);
  54. Prototype void asm_fltconst(Exp *, Stor *, long *);
  55. Prototype void CallFPSupport(Exp *, long, Stor *, Stor *, Stor *, char *, short);
  56. Prototype void asm_layoutfpconst(Exp *, Stor *, Stor *);
  57.  
  58. Prototype void ConstFpNeg(Exp *, Stor *, Stor *);
  59. Prototype void ConstFpAdd(Exp *, Stor *, Stor *, Stor *);
  60. Prototype void ConstFpSub(Exp *, Stor *, Stor *, Stor *);
  61. Prototype void ConstFpMul(Exp *, Stor *, Stor *, Stor *);
  62. Prototype void ConstFpDiv(Exp *, Stor *, Stor *, Stor *);
  63. Prototype void CloseLibsExit(void);
  64.  
  65. Library *MathIeeeDoubTransBase;
  66. Library *MathIeeeDoubBasBase;
  67. Library *MathIeeeSingTransBase;
  68. Library *MathIeeeSingBasBase;
  69. Library *MathBase;
  70. Library *MathTransBase;
  71.  
  72. Local void TmpFpAdd(TmpFlt *, TmpFlt *);
  73.  
  74. void
  75. asm_fpadd(exp, t, s1, s2, d)
  76. Exp *exp;
  77. Type *t;
  78. Stor *s1, *s2, *d;
  79. {
  80.     CallFPSupport(exp, t->Size, s1, s2, d, "add", -1);
  81. }
  82.  
  83. void
  84. asm_fpsub(exp, t, s1, s2, d)
  85. Exp *exp;
  86. Type *t;
  87. Stor *s1, *s2, *d;
  88. {
  89.     CallFPSupport(exp, t->Size, s1, s2, d, "sub", 1);
  90. }
  91.  
  92. void
  93. asm_fpmul(exp, t, s1, s2, d)
  94. Exp *exp;
  95. Type *t;
  96. Stor *s1, *s2, *d;
  97. {
  98.     CallFPSupport(exp, t->Size, s1, s2, d, "mul", -1);
  99. }
  100.  
  101. void
  102. asm_fpdiv(exp, t, s1, s2, d)
  103. Exp *exp;
  104. Type *t;
  105. Stor *s1, *s2, *d;
  106. {
  107.     CallFPSupport(exp, t->Size, s1, s2, d, "div", 1);
  108. }
  109.  
  110. void
  111. asm_fpneg(exp, t, s, d)
  112. Exp *exp;
  113. Type *t;
  114. Stor *s, *d;
  115. {
  116.     Assert(t);
  117.     /*printf("type %08lx id %d\n", t, t->Id);*/
  118.     CallFPSupport(exp, t->Size, s, NULL, d, "neg", 1);
  119. }
  120.  
  121. void
  122. asm_fpcmp(exp, s1, s2, pcond)
  123. Exp *exp;
  124. Stor *s1, *s2;
  125. short *pcond;
  126. {
  127.     CallFPSupport(exp, s1->st_Size, s1, s2, NULL, "cmp", 1);
  128. }
  129.  
  130. void
  131. asm_fptest(exp, s)
  132. Exp *exp;
  133. Stor *s;
  134. {
  135.     CallFPSupport(exp, s->st_Size, s, NULL, NULL, "tst", 1);
  136. }
  137.  
  138. void
  139. asm_fptoint(exp, s, d)
  140. Exp *exp;
  141. Stor *s;
  142. Stor *d;
  143. {
  144.     Stor rd0;
  145.  
  146.     CallFPSupport(exp, s->st_Size, s, NULL, NULL, "fix", 1);
  147.     AllocDataRegisterAbs(&rd0, 4, RB_D0);
  148.     rd0.st_Size = d->st_Size;
  149.     asm_move(exp, &rd0, d);
  150.     FreeRegister(&rd0);
  151. }
  152.  
  153. void
  154. asm_inttofp(exp, s, d)
  155. Exp *exp;
  156. Stor *s;
  157. Stor *d;
  158. {
  159.     Stor rd0;
  160.     AllocDataRegisterAbs(&rd0, 4, RB_D0);
  161.     asm_ext(exp, s, &rd0, s->st_Flags);
  162.     FreeRegister(&rd0);
  163.     CallFPSupport(exp, d->st_Size, NULL, NULL, d, "flt", 1);
  164. }
  165.  
  166. void
  167. asm_fptofp(exp, s, d)
  168. Exp *exp;
  169. Stor *s;
  170. Stor *d;
  171. {
  172.     char name[16];
  173.  
  174.     if (s->st_Size == d->st_Size) {
  175.     asm_move(exp, s, d);
  176.     return;
  177.     }
  178.  
  179.     switch(s->st_Size) {
  180.     case 4:
  181.     if (FFPOpt)
  182.         strcpy(name, "ffp");
  183.     else
  184.         strcpy(name, "sp");
  185.     break;
  186.     case 8:
  187.     strcpy(name, "dp");
  188.     break;
  189.     case 16:
  190.     strcpy(name, "xp");
  191.     break;
  192.     default:
  193.     dbprintf(("illegal/unsupported fp-fp conversion"));
  194.     Assert(0);
  195.     break;
  196.     }
  197.  
  198.     strcat(name, "to");
  199.  
  200.     switch(d->st_Size) {
  201.     case 4:
  202.     if (FFPOpt)
  203.         strcat(name, "ffp");
  204.     else
  205.         strcat(name, "sp");
  206.     break;
  207.     case 8:
  208.     strcat(name, "dp");
  209.     break;
  210.     case 16:
  211.     strcat(name, "xp");
  212.     break;
  213.     default:
  214.     dbprintf(("illegal/unsupported fp-fp conversion"));
  215.     Assert(0);
  216.     break;
  217.     }
  218.  
  219.     CallFPSupport(exp, 99, s, NULL, d, name, 1);
  220. }
  221.  
  222. void
  223. CloseLibsExit(void)
  224. {
  225. #ifdef AMIGA
  226.     if (MathIeeeDoubTransBase) {
  227.     CloseLibrary((void *)MathIeeeDoubTransBase);
  228.     MathIeeeDoubTransBase = 0;
  229.     }
  230.     if (MathIeeeDoubBasBase) {
  231.     CloseLibrary((void *)MathIeeeDoubBasBase);
  232.     MathIeeeDoubBasBase = 0;
  233.     }
  234.     if (MathIeeeSingTransBase) {
  235.     CloseLibrary((void *)MathIeeeSingTransBase);
  236.     MathIeeeSingTransBase = 0;
  237.     }
  238.     if (MathIeeeSingBasBase) {
  239.     CloseLibrary((void *)MathIeeeSingBasBase);
  240.     MathIeeeSingBasBase = 0;
  241.     }
  242.     if (MathBase) {
  243.     CloseLibrary((void *)MathBase);
  244.     MathBase = 0;
  245.     }
  246.     if (MathTransBase) {
  247.     CloseLibrary((void *)MathTransBase);
  248.     MathTransBase = 0;
  249.     }
  250. #endif
  251. }
  252.  
  253. /*
  254.  *  lay down an fp value according to size and format and modify the storage
  255.  *  accordingly.
  256.  */
  257.  
  258. #ifdef AMIGA
  259.  
  260. void
  261. asm_fltconst(exp, s, ary)
  262. Exp *exp;
  263. Stor *s;
  264. long *ary;
  265. {
  266.     static int LibsOpen = 0;
  267.  
  268.  
  269.     switch(LibsOpen) {
  270.     case 0:
  271.     {
  272.         int error = 0;
  273.         int xerr;
  274.  
  275.         if (FFPOpt == 0) {
  276.         if ((MathIeeeSingBasBase = (void *)OpenLibrary("mathieeesingbas.library", 0)) == NULL)
  277.             ++error;
  278.         if ((MathIeeeSingTransBase= (void *)OpenLibrary("mathieeesingtrans.library", 0)) == NULL)
  279.             ++error;
  280.         if (error) {
  281.             zerror(EERROR_CANT_OPEN_MATHLIB, "mathieeesing[bas,trans].library");
  282.         }
  283.         } else {
  284.         if ((MathBase = (void *)OpenLibrary("mathffp.library", 0)) == NULL)
  285.             ++error;
  286.         if ((MathTransBase = (void *)OpenLibrary("mathtrans.library", 0)) == NULL)
  287.             ++error;
  288.         if (error)
  289.             zerror(EERROR_CANT_OPEN_MATHLIB, "math[ffp,trans].library");
  290.         }
  291.         xerr = error;
  292.         if ((MathIeeeDoubBasBase = (void *)OpenLibrary("mathieeedoubbas.library", 0)) == NULL)
  293.         ++error;
  294.         if ((MathIeeeDoubTransBase = (void *)OpenLibrary("mathieeedoubtrans.library", 0)) == NULL)
  295.         ++error;
  296.  
  297.         if (error)
  298.         LibsOpen = 2;
  299.         else
  300.         LibsOpen = 1;
  301.         if (xerr != error)
  302.         zerror(EERROR_CANT_OPEN_MATHLIB, "mathieeedoub[bas,trans].library");
  303.     }
  304.     break;
  305.     case 1:
  306.     break;
  307.     case 2:
  308.     return;
  309.     }
  310.  
  311.     switch(s->st_Size) {
  312.     case 4:
  313.     strncpy(TmpBuf, s->st_FltConst, s->st_FltLen);
  314.     TmpBuf[s->st_FltLen] = 0;
  315.  
  316.     if (FFPOpt == 0) {
  317.         float acc;           /*  accumulated value   */
  318.         float ten = IEEESPFlt(10);
  319.         short x;
  320.  
  321.         /*
  322.          *    <TmpBuf> x 10^X    Convert a digit at a time, exponent
  323.          *    counts digits
  324.          */
  325.  
  326.         x = FPrefix(exp, s->st_FltConst, s->st_FltLen, TmpBuf);
  327.  
  328.         acc = IEEESPFlt(0);
  329.         {
  330.         char c;
  331.         short i;
  332.  
  333.         for (i = 0; (c = TmpBuf[i+1]) && i < 9; ++i) {
  334.             acc = IEEESPAdd(IEEESPMul(acc, ten), IEEESPFlt(c - '0'));
  335.             --x;
  336.         }
  337.         }
  338.         if (x < 0)
  339.         acc = IEEESPDiv(acc, IEEESPPow(IEEESPFlt(-x), ten));
  340.         if (x > 0)
  341.         acc = IEEESPMul(acc, IEEESPPow(IEEESPFlt(x), ten));
  342.  
  343.         if (TmpBuf[0] == -1)
  344.         acc = IEEESPNeg(acc);
  345.  
  346.         ary[0] = ((long *)&acc)[0];
  347.     } else {
  348.         {                    /*    fix bug in afp()    */
  349.         char *ptr;
  350.         if (ptr = strchr(TmpBuf, 'e'))
  351.             *ptr = 'E';
  352.         }
  353.         ary[0] = afp(TmpBuf);        /*    amiga.lib routine */
  354.     }
  355.     break;
  356.     case 8:
  357.     {
  358.         double acc;     /*  accumulated value    */
  359.         double ten = IEEEDPFlt(10);
  360.         short x;
  361.  
  362.         /*
  363.          *    <TmpBuf> x 10^X    Convert a digit at a time.
  364.          */
  365.  
  366.         x = FPrefix(exp, s->st_FltConst, s->st_FltLen, TmpBuf);
  367.  
  368.         acc = IEEEDPFlt(0);
  369.         {
  370.         char c;
  371.         short i;
  372.  
  373.         for (i = 0; (c = TmpBuf[i+1]) && i < 17; ++i) {
  374.             acc = IEEEDPAdd(IEEEDPMul(acc, ten), IEEEDPFlt(c - '0'));
  375.             --x;
  376.         }
  377.         }
  378.         if (x < 0)
  379.         acc = IEEEDPDiv(acc, IEEEDPPow(IEEEDPFlt(-x), ten));
  380.         if (x > 0)
  381.         acc = IEEEDPMul(acc, IEEEDPPow(IEEEDPFlt(x), ten));
  382.  
  383.         if (TmpBuf[0] == -1)
  384.         acc = IEEEDPNeg(acc);
  385.  
  386.         ary[0] = ((long *)&acc)[0];
  387.         ary[1] = ((long *)&acc)[1];
  388.     }
  389.     break;
  390.     case 16:
  391.     dbprintf(("long dbl flt const not implemented"));
  392.     Assert(0);
  393.     break;
  394.     default:
  395.     dbprintf(("asm_fltconst: bad size %d\n", s->st_Size));
  396.     Assert(0);
  397.     break;
  398.     }
  399. }
  400.  
  401. #else
  402.  
  403. void
  404. asm_fltconst(exp, s, ary)
  405. Exp *exp;
  406. Stor *s;
  407. long *ary;
  408. {
  409.     TmpBuf[0] = 0;    /* prevent unused var warning */
  410.     dbprintf(("asm_fltconst: not implemented\n"));
  411.     Assert(0);
  412. }
  413.  
  414. #endif
  415.  
  416. /*
  417.  *  Compiler support call (passing arbitrarily sized arguments)
  418.  *
  419.  *  order = 1        order = 0        order = -1
  420.  *
  421.  *  LEA(s1),A0        LEA(s1),A1        any order
  422.  *  LEA(s2),A1        LEA(s2),A0
  423.  *
  424.  *  call routine    (such as __fpsub_a : s1 - s2)
  425.  *  result in D0  or  D0/D1  or  D0/D1/A0/A1,  write -> d
  426.  *  done
  427.  */
  428.  
  429. #ifdef REGISTERED
  430.  
  431. void
  432. CallFPSupport(
  433.     Exp *exp,
  434.     long prec,
  435.     Stor *s1,
  436.     Stor *s2,
  437.     Stor *d,
  438.     char *fnam,
  439.     short orderReq
  440. ) {
  441.     char buf[32];
  442.     char *mop;
  443.     short len;
  444.     Stor ss1;
  445.     Stor ss2;
  446.  
  447.     switch(prec) {
  448.     case 99:
  449.     strcpy(buf, "__cv");
  450.     break;
  451.     case 4:
  452.     if (FFPOpt)
  453.         strcpy(buf, "__ffp");
  454.     else
  455.         strcpy(buf, "__sp");
  456.     break;
  457.     case 8:
  458.     strcpy(buf, "__dp");
  459.     break;
  460.     case 16:
  461.     strcpy(buf, "__xp");
  462.     break;
  463.     default:
  464.     strcpy(buf, "__??");
  465.     break;
  466.     }
  467.     strcat(buf, fnam);
  468.     len = strlen(buf);
  469.     buf[len++] = '_';
  470.     buf[len++] = MathMode;
  471.     buf[len] = 0;
  472.  
  473.     mop = strdup(buf);
  474.  
  475.     if (prec == 4) {        /*    use Dn interface for single precision fp    */
  476.     CallAsmSupport(exp, mop + 2, s1, s2, d, orderReq);
  477.     return;
  478.     }
  479.  
  480.     GenFlagCallMade();
  481.     AddAuxSub(mop + 2);
  482.  
  483.     /*
  484.      *    LEA s1 -> A0        EXCEPT FOR FLOATS, PASS IN D0 (s2 is NULL)
  485.      *    LEA s2 -> A1
  486.      *    result in D0 or D0/D1 or D0/D1/A0/A1
  487.      *
  488.      *    Handle floating constant
  489.      */
  490.  
  491.     if (s1 && s1->st_Type == ST_FltConst) {
  492.     asm_layoutfpconst(exp, s1, &ss1);
  493.     s1 = &ss1;
  494.     }
  495.     if (s2 && s2->st_Type == ST_FltConst) {
  496.     asm_layoutfpconst(exp, s2, &ss2);
  497.     s2 = &ss2;
  498.     }
  499.  
  500.     {
  501.     Stor rd0, rd1;
  502.     Stor ra0, ra1;
  503.  
  504.     GenFlagCallMade();
  505.  
  506.     AllocDataRegisterAbs(&rd0, 4, RB_D0);
  507.     AllocDataRegisterAbs(&rd1, 4, RB_D1);
  508.     AllocAddrRegisterAbs(&ra0, RB_A0);
  509.     AllocAddrRegisterAbs(&ra1, RB_A1);
  510.  
  511.     /*
  512.      *  lea s1 -> A0    but if s2 is rel A0 then use temporary
  513.      *  lea s2 -> A1
  514.      */
  515.  
  516.     if (s1 && s2) {
  517.         Assert(prec != 99);
  518.  
  519.         if (SameRegister(s2, &ra0)) {
  520.         if (SameRegister(s1, &ra1)) {
  521.             /*
  522.              *    put into reversed regs. If orderReq then exg
  523.              *    back to normal
  524.              */
  525.  
  526.             asm_lea(exp, s1, 0, &ra1);
  527.             asm_lea(exp, s2, 0, &ra0);
  528.             if (orderReq > 0)
  529.             printf("\texg\tA0,A1\n");
  530.         } else {
  531.             if (orderReq > 0) {
  532.             asm_lea(exp, s2, 0, &ra1);
  533.             asm_lea(exp, s1, 0, &ra0);
  534.             } else {
  535.             asm_lea(exp, s2, 0, &ra0);
  536.             asm_lea(exp, s1, 0, &ra1);
  537.             }
  538.         }
  539.         } else {
  540.         /*
  541.          *  put into reg A0 first, then A1, if orderReq is 0 then
  542.          *  reverse them.
  543.          */
  544.  
  545.         asm_lea(exp, s1, 0, &ra0);
  546.         asm_lea(exp, s2, 0, &ra1);
  547.         if (orderReq == 0)
  548.             printf("\texg\tA0,A1\n");
  549.         }
  550.     } else if (s1) {
  551.         if (s1->st_Size == 4) {
  552.         /*printf("** BUF = %s, prec = %d, s1 = %08lx siz=%d\n", buf, prec, s1, s1->st_Size);*/
  553.         Assert(prec == 99);    /*  only way!    */
  554.         asm_move(exp, s1, &rd0);
  555.         } else {
  556.         asm_lea(exp, s1, 0, &ra0);
  557.         }
  558.     } else if (s2) {
  559.         Assert(prec != 99);
  560.         asm_lea(exp, s2, 0, &ra1);
  561.     }
  562.  
  563.     if (SmallCode)
  564.         printf("\tjsr\t%s(pc)\n", mop);
  565.     else
  566.         printf("\tjsr\t%s\n", mop);
  567.  
  568.     /*
  569.      *  Result in D0 [D1 [ A0 A1]] depending on size.
  570.      */
  571.  
  572.     if (d) {
  573.         if ((d->st_Type == ST_Reg || d->st_Type == ST_RelReg) && (d->st_RegNo == RB_A0 || d->st_RegNo == RB_A1)) {
  574.         RegFlagTryAgain();  /*    required?   */
  575.         /*
  576.         dbprintf(("dest is A0 or A1"));
  577.         */
  578.         }
  579.  
  580.         if (d->st_Size == 4) {    /*  move    */
  581.         asm_move(exp, &rd0, d);
  582.         } else {            /*  movem   */
  583.         switch(d->st_Size) {
  584.         case 4:         /*  case occurs when converting */
  585.             printf("\tmove.l\tD0");
  586.             break;
  587.         case 8:
  588.             printf("\tmovem.l\tD0/D1");
  589.             break;
  590.         case 16:
  591.             printf("\tmovem.l\tD0/D1/A0/A1");
  592.             break;
  593.         }
  594.         printf(",%s\n", StorToString(d, NULL));
  595.         }
  596.     }
  597.  
  598.     FreeRegister(&rd0);
  599.     FreeRegister(&rd1);
  600.     FreeRegister(&ra0);
  601.     FreeRegister(&ra1);
  602.     }
  603. }
  604.  
  605. #else
  606.  
  607. void
  608. CallFPSupport(Exp *exp, long prec, Stor *s1, Stor *s2, Stor *d, char *fnam, short orderReq)
  609. {
  610.     cerror(EUNREG, "asm_fp: floating point");
  611. }
  612.  
  613. #endif
  614.  
  615. void
  616. asm_layoutfpconst(exp, s, d)
  617. Exp *exp;
  618. Stor *s;
  619. Stor *d;
  620. {
  621.     long fpv[4];
  622.     long l = AllocLabel();
  623.  
  624.     asm_segment(&DummyDataVar);
  625.     asm_fltconst(exp, s, fpv);
  626.     puts("\tds.w\t0");
  627.     printf("l%ld\tdc.l\t$%08lx", l, fpv[0]);
  628.     if (s->st_Size >= 8)
  629.     printf(",$%08lx", fpv[1]);
  630.     if (s->st_Size >= 16) {
  631.     printf(",$%08lx", fpv[2]);
  632.     printf(",$%08lx", fpv[3]);
  633.     }
  634.     puts("");
  635.     asm_segment(&DummyCodeVar);
  636.     d->st_Type = ST_RelLabel;
  637.     d->st_Offset = 0;
  638.     d->st_Label = l;
  639.     d->st_Flags = 0;
  640.     d->st_Size = s->st_Size;
  641. }
  642.  
  643. /*
  644.  *            CONSTANT FLOATING POINT ROUTINES
  645.  */
  646.  
  647. static TmpFlt f1, f2;
  648.  
  649. void
  650. ConstFpNeg(exp, s, d)
  651. Exp *exp;
  652. Stor *s, *d;
  653. {
  654.     StorToTmpFlt(exp, s, &f1);
  655.     f1.tf_Negative = !f1.tf_Negative;
  656.     TmpFltToStor(exp, &f1, d);
  657. }
  658.  
  659.  
  660. void
  661. ConstFpAdd(exp, s1, s2, d)
  662. Exp *exp;
  663. Stor *s1, *s2, *d;
  664. {
  665.     StorToTmpFlt(exp, s1, &f1);
  666.     StorToTmpFlt(exp, s2, &f2);
  667.     TmpFpAdd(&f1, &f2);
  668.     TmpFltToStor(exp, &f2, d);
  669. }
  670.  
  671. void
  672. ConstFpSub(exp, s1, s2, d)
  673. Exp *exp;
  674. Stor *s1, *s2, *d;
  675. {
  676.     StorToTmpFlt(exp, s1, &f1);
  677.     StorToTmpFlt(exp, s2, &f2);
  678.     f2.tf_Negative = !f2.tf_Negative;
  679.     TmpFpAdd(&f1, &f2);
  680.     TmpFltToStor(exp, &f2, d);
  681. }
  682.  
  683. Local void
  684. TmpFpAdd(s, d)
  685. TmpFlt *s;
  686. TmpFlt *d;
  687. {
  688.     BalanceTmpFlt(s, d);
  689.  
  690.     if ((s->tf_Negative ^ d->tf_Negative) == 0) {
  691.     short i;
  692.     ulong v;
  693.     ulong c = 0;
  694.  
  695.     if (s->tf_WMantissa[0] + d->tf_WMantissa[0] + 1 > 0xFFFF) {
  696.         dbprintf(("acx"));
  697.         TmpFltMantDiv(s->tf_WMantissa, 8, 10);
  698.         TmpFltMantDiv(d->tf_WMantissa, 8, 10);
  699.         ++s->tf_Exponent;
  700.         ++d->tf_Exponent;
  701.     }
  702.     for (i = 7; i >= 0; --i) {
  703.         v = s->tf_WMantissa[i] + d->tf_WMantissa[i] + c;
  704.         d->tf_WMantissa[i] = v;
  705.         c = v >> 16;
  706.     }
  707.     } else {
  708.     /*
  709.      *  do: d = d - s;  keep d's sign, if the result of the absolute
  710.      *            subtraction is negative the negate d
  711.      */
  712.  
  713.     short i;
  714.     ulong b = 0;
  715.  
  716.     for (i = 7; i >= 0; --i) {
  717.         ulong v = d->tf_WMantissa[i] - s->tf_WMantissa[i] - b;
  718.         if ((long)v < 0)
  719.         b = 1;
  720.         else
  721.         b = 0;
  722.         d->tf_WMantissa[i] = v;
  723.     }
  724.     if (b) {    /*  abs(d) < abs(s)   */
  725.         /* b = 1 */
  726.         for (i = 7; i >= 0; --i) {
  727.         ulong v = (uword)~d->tf_WMantissa[i] + b;
  728.         if (v > 0xFFFF)
  729.             b = 1;
  730.         else
  731.             b = 0;
  732.         d->tf_WMantissa[i] = v;
  733.         }
  734.         d->tf_Negative = !d->tf_Negative;
  735.     }
  736.     }
  737.     NormalizeTmpFlt(d);
  738. }
  739.  
  740. /*
  741.  *  Constant floating point multiply
  742.  */
  743.  
  744. void
  745. ConstFpMul(exp, s1, s2, d)
  746. Exp *exp;
  747. Stor *s1, *s2, *d;
  748. {
  749.     short i, j;
  750.     uword res[16];
  751.  
  752.     StorToTmpFlt(exp, s1, &f1);
  753.     StorToTmpFlt(exp, s2, &f2);
  754.  
  755.     setmem(res, sizeof(res), 0);
  756.  
  757.     for (j = 7; j >= 0; --j) {
  758.     uword *rptr;
  759.     for (i = 7, rptr = res + j + 8; i >= 0; --i, --rptr) {
  760.         ulong v = f1.tf_WMantissa[i] * f2.tf_WMantissa[j];
  761.         uword *tptr = rptr;
  762.  
  763.         while (v) {
  764.         Assert(tptr >= res);
  765.         v = v + *tptr;
  766.         *tptr = v;
  767.         v >>= 16;
  768.         --tptr;
  769.         }
  770.     }
  771.     }
  772.  
  773.     /*
  774.      *    Divide until solution fits in 16 bytes
  775.      */
  776.  
  777.     while (((ulong *)res)[0] | ((ulong *)res)[1] | ((ulong *)res)[2] | ((ulong *)res)[3]) {
  778.     TmpFltMantDiv(res, 16, 10000);
  779.     f2.tf_Exponent += 4;
  780.     }
  781.  
  782.     f2.tf_Negative = f1.tf_Negative ^ f2.tf_Negative;
  783.     f2.tf_Exponent += f1.tf_Exponent;
  784.     f2.tf_LMantissa[0] = ((ulong *)res)[4];
  785.     f2.tf_LMantissa[1] = ((ulong *)res)[5];
  786.     f2.tf_LMantissa[2] = ((ulong *)res)[6];
  787.     f2.tf_LMantissa[3] = ((ulong *)res)[7];
  788.     NormalizeTmpFlt(&f2);
  789.     TmpFltToStor(exp, &f2, d);
  790. }
  791.  
  792. void
  793. ConstFpDiv(exp, s1, s2, d)
  794. Exp *exp;
  795. Stor *s1, *s2, *d;
  796. {
  797.     uword res[16];            /*    result        */
  798.     uword cmp[8];            /*    compare     */
  799.     short bit;
  800.  
  801.     StorToTmpFlt(exp, s1, &f1);
  802.     StorToTmpFlt(exp, s2, &f2);
  803.  
  804.     /*
  805.      * If msb bit is a 1, our shift/compare will overflow,
  806.      * so we have to shift it right one.
  807.      */
  808.  
  809.     if (f2.tf_WMantissa[0] > 0x7FFF) {
  810.         TmpFltMantDiv(f2.tf_WMantissa, 8, 10);
  811.         ++f2.tf_Exponent;
  812.     }
  813.  
  814.     setmem(res, sizeof(res), 0);    /*    clear result    */
  815.     setmem(cmp, sizeof(cmp), 0);    /*    clear compare    */
  816.  
  817.     for (bit = 0; bit < 256; ++bit) {
  818.     short i;
  819.     ulong b;
  820.  
  821.     /*
  822.      *  shift bit into cmp from f1
  823.      */
  824.  
  825.     {
  826.         ulong *lp;
  827.         ulong v;
  828.  
  829.         for (lp = f1.tf_LMantissa + 3, b = 0; lp >= f1.tf_LMantissa; --lp) {
  830.         v = (*lp << 1) | b;
  831.         b = 0;
  832.         if ((long)*lp < 0)
  833.             b = 1;
  834.         *lp = v;
  835.         }
  836.         for (lp = (ulong *)cmp + 3; lp >= (ulong *)cmp; --lp) {
  837.         v = (*lp << 1) | b;
  838.         b = 0;
  839.         if ((long)*lp < 0)
  840.             b = 1;
  841.         *lp = v;
  842.         }
  843.     }
  844.     if (b)
  845.     {
  846.         dbprintf(("fp constant divide"));
  847.         Assert(0);
  848.     }
  849.  
  850.     dbprintf(("cmp: %04x%04x%04x%04x%04x%04x%04x%04x\n", cmp[0], cmp[1], cmp[2], cmp[3], cmp[4], cmp[5], cmp[6], cmp[7]));
  851.  
  852.     /*
  853.      *  can we subtract ? i.e. f2 <= cmp ?
  854.      */
  855.  
  856.     for (i = 0; i < 7; ++i) {
  857.         if (f2.tf_WMantissa[i] < cmp[i])
  858.         break;
  859.         if (f2.tf_WMantissa[i] > cmp[i])
  860.         goto skip;
  861.     }
  862.  
  863.     dbprintf((";subok\n"));
  864.  
  865.     /*
  866.      *  yes, set bit in result
  867.      */
  868.  
  869.     res[bit >> 4] |= 0x8000 >> (bit & 15);
  870.  
  871.     /*
  872.      *  subtract
  873.      */
  874.  
  875.     for (i = 7, b = 0; i >= 0; --i) {
  876.         ulong v = cmp[i] - f2.tf_WMantissa[i] - b;
  877.         b = 0;
  878.         if ((long)v < 0)
  879.         b = 1;
  880.         cmp[i] = v;
  881.     }
  882. skip:
  883.     ;
  884.     }
  885.  
  886.     dbprintf(("res: %04x%04x%04x%04x%04x%04x%04x%04x %04x%04x%04x%04x%04x%04x%04x%04x\n",
  887.     res[0], res[1], res[2], res[3], res[4], res[5], res[6], res[7],
  888.     res[8], res[9], res[10],res[11],res[12],res[13],res[14],res[15]
  889.     ));
  890.  
  891.     /*
  892.      *    Multiply until left justified, solution is first 4 longwords
  893.      *
  894.      *    bit limits loop incase we are dealing with a 0 result.
  895.      */
  896.  
  897.     for (bit = 0; res[0] == 0 && bit < 32; ++bit) {
  898.     TmpFltMantMul(res, 16, 10000);
  899.     f1.tf_Exponent -= 4;
  900.     }
  901.     for (bit = bit; res[0] < (uword)(0xFFFF / 10 - 10) && bit < 32; ++bit) {
  902.     TmpFltMantMul(res, 16, 10);
  903.     f1.tf_Exponent -= 1;
  904.     }
  905.  
  906.     f2.tf_Negative = f1.tf_Negative ^ f2.tf_Negative;
  907.     f2.tf_Exponent = f1.tf_Exponent - f2.tf_Exponent;
  908.     f2.tf_LMantissa[0] = ((ulong *)res)[0];
  909.     f2.tf_LMantissa[1] = ((ulong *)res)[1];
  910.     f2.tf_LMantissa[2] = ((ulong *)res)[2];
  911.     f2.tf_LMantissa[3] = ((ulong *)res)[3];
  912.     NormalizeTmpFlt(&f2);
  913.     TmpFltToStor(exp, &f2, d);
  914. }
  915.  
  916.  
  917.